<template>
<div>
    <div class="container-fluid">
        <br><br class="hidden-xs">
        <div v-if="search" class="row col-xs-10 col-xs-offset-1 col-md-6 col-md-offset-3">
            <div class="form-group has-feedback" v-if="!online_dropdown">
                <input type="text" class="form-control" autocomplete="off" placeholder="搜索" v-model.trim="query" @keyup.enter="doSearch" ref="search" id="input-search" style="padding-left:30px; padding-right:10px;">
                <span class="glyphicon glyphicon-search form-control-feedback text-gray" style="left:0;"></span>
            </div>
            <div class="input-group" style="width:100%;" v-else>
                <div class="input-group-btn">
                    <button id="input-online-dropdown" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-top-left-radius:0;border-bottom-left-radius:0;">
                        {{onlineText}} <span class="caret"></span>
                    </button>
                    <ul id="input-online-menu" class="dropdown-menu">
                        <li><a role="button">全部</a></li>
                        <li><a role="button" data-online="1">在线</a></li>
                        <li><a role="button" data-online="0">离线</a></li>
                    </ul>
                </div>
                <input type="text" class="form-control" autocomplete="off" placeholder="搜索" v-model.trim="query" @keyup.enter="doSearch" ref="search" id="input-search">
            </div>
        </div>
        <br v-if="search"><br v-if="search"><br v-if="search"><br v-if="search" class="hidden-xs">
        <div class="view-icons">
            <div class="col-sm-6 col-md-3" v-for="channelInfo in Channels" :key="channelInfo.Channel">
                <div class="thumbnail">
                    <div class="wrapper">
                        <div class="inner">
                            <img onerror="this.src='/images/default_snap.png';" v-on:click="player(channelInfo)" :src="channelInfo.SnapURL" loading="lazy">
                        </div>
                        <div class="mask" v-if="channelInfo.Online != 1 && serverInfo.ChannelSnapInterval"></div>
                    </div>
                    <router-link :to="`/record/timeview/${channelInfo.Channel}`" class="record" v-if="channelInfo.RecordReserveDays && serverInfo.VersionType != '标准版'">
                        回放
                    </router-link>
                    <router-link :to="`/playback/timeview/${channelInfo.Channel}`" class="playback" v-else-if="channelInfo.Online == 1 && (channelInfo.DeviceType.endsWith('SDK') || channelInfo.DeviceType == 'ISUP')">
                        回放
                    </router-link>
                    <span class="stream-info" v-if="channelInfo.Streaming">{{formatStreamInfo(channelInfo)}}</span>
                    <div :class="['title', {'text-primary': channelInfo.Online == 1 && (!channelInfo.SourceVideoCodecName || channelInfo.SourceVideoCodecName == 'h264'),
                        'text-orange': channelInfo.Online == 1 && channelInfo.SourceVideoCodecName && channelInfo.SourceVideoCodecName != 'h264',
                        'text-gray': channelInfo.Online != 1}]">
                        <small class="row no-margin no-padding">
                            <div class="channel-name col-xs-7 no-padding no-margin ellipsis">[{{channelInfo.Channel}}] {{channelInfo.Name}}</div>
                            <div class="channel-status text-right col-xs-5 no-padding no-margin ellipsis">
                                <a role="button" :title="channelInfo.ErrorString" v-if="hasAnyRole(serverInfo, userInfo, '超级管理员', '管理员')" @click="showChannelLog(channelInfo)" style="color:inherit !important;">
                                    <i :class="['fa', {'fa-check-circle': channelInfo.Online == 1, 'fa-times-circle': channelInfo.Online != 1}]"></i>
                                    {{channelInfo.Online == 1 ? "在线" : "离线"}}
                                </a>
                                <span class="channel-status-text" :title="channelInfo.ErrorString" v-else>
                                    <i :class="['fa', {'fa-check-circle': channelInfo.Online == 1, 'fa-times-circle': channelInfo.Online != 1}]"></i>
                                    {{channelInfo.Online == 1 ? "在线" : "离线"}}
                                </span>
                            </div>
                        </small>
                    </div>
                </div>
            </div>
            <infinite-loading @infinite="loadMore" spinner="waveDots" force-use-infinite-wrapper="true" ref="iconLoadMore" :identifier="iconLoadMoreId">
                <span slot="no-results" class="empty-channels">
                    {{this.q != '' || this.online != '' ? "该条件未搜索到视频通道" : "当前没有通道，记得配置通道哦！"}}
                </span>
                <span slot="no-more"></span>
            </infinite-loading>
        </div>
    </div>
    <ChannelLogDlg ref="channelLogDlg"></ChannelLogDlg>
</div>
</template>

<script>
import { mapState } from "vuex";
import _ from 'lodash';
import InfiniteLoading from 'vue-infinite-loading';
import ChannelLogDlg from 'components/ChannelLogDlg.vue';

export default {
    components: {
        InfiniteLoading, ChannelLogDlg
    },
    data() {
        return {
            query: "",
            Channels: [],
            limit: 12,
            iconLoadMoreId: new Date().getTime(),
            iframe: false,
            aspect: "",
            share: true,
            menu: "",
            ptz: "",
            online: "",
            online_dropdown: true,
            timer: 0,
            search: true,
            ctrl: false,
        };
    },
    props: {
        mode: {
            type: String,
            default: "icons"
        },
        q: {
            type: String,
            default: ""
        }
    },
    mounted() {
        this.menu = this.getQueryString("menu", "");
        this.ptz = this.getQueryString("ptz", "");
        this.search = this.getQueryString("search", "yes") == "yes";
        this.share = this.getQueryString("share", "yes") == "yes";
        this.iframe = this.getQueryString("iframe", "no") == "yes";
        this.aspect = this.getQueryString("aspect").replace("x", ":");
        this.online_dropdown = this.getQueryString("online_dropdown", "yes") == "yes";
        this.online = this.getQueryString("online", "");
        if(this.online == "yes") {
            this.online = "1";
        }
        // this.$refs["search"].focus();
        this.query = this.q;
        var vm = this;
        $(document).on('expanded.pushMenu collapsed.pushMenu', () => {
            //this.resizeNiceScroll();
        }).on("click", "#input-online-menu a", function() {
            vm.online = $(this).attr("data-online") || "";
        }).on("keydown", this.keyDown).on("keyup", this.keyUp);
    },
    methods: {
        getQueryString(name, defVal = "") {
            var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
            var r = window.location.search.substr(1).match(reg);
            if (r != null) {
                return unescape(r[2]);
            }
            return defVal;
        },
        play(video) {
            this.$emit("play", video);
        },
        player(channelInfo) {
            var p = "&back=yes";
            if (this.ctrl) {
                p = "";
            }
            if (this.iframe) {
                p = p + "&iframe=yes";
            }
            if (this.ptz) {
                p = p + "&ptz=" + this.ptz;
            }
            if (this.aspect != "") {
                p = p + "&aspect=" + this.aspect;
            }
            if (!this.share) {
                p = p + "&share=no";
            }
            if (this.menu != "") {
                p = p + "&menu=" + this.menu;
            }
            if (!this.search) {
                p = p + "&search=no";
            }
            if (this.q != "") {
                p = p + "&q=" + encodeURI(encodeURI(this.q));
            }
            if (this.online) {
                p = p + "&online=" + this.online;
            }
            if (!this.online_dropdown) {
                p = p + "&online_dropdown=no";
            }
            var link = `/play.html?channel=${channelInfo.Channel}${p}`;
            if (this.ctrl) {
                window.open(link, "_blank");
            } else {
                location.href = link;
            }
        },
        getchannels() {
            $.get("/api/v1/getchannels", {
                q: this.query,
                online: this.online,
                start: 0,
                limit: this.limit
            }).then(data => {
                this.Channels = (data.LiveQing || data.NVR).Body.Channels || [];
            });
        },
        ready() {
            this.$watch('query', function(newVal, oldVal) {
                this.doSearch();
            });
            this.$watch('online', function(newVal, oldVal) {
                this.doQuery();
            });
        },
        doQuery() {
            var query = {};
            if(this.query) query["q"] = this.query;
            if(this.online) query["online"] = this.online;
            if(!this.online_dropdown) query["online_dropdown"] = "no";
            this.$router.replace({
                path: `/index/icons`,
                query: query,
            });
        },
        doSearch: _.debounce(function () {
            this.doQuery();
        }, 500),
        loadMore(state) {
            $.get("/api/v1/getchannels", {
                q: this.query,
                online: this.online,
                start: this.Channels.length,
                limit: this.limit
            }).then(data => {
                var rows = (data.LiveQing || data.NVR).Body.Channels || [];
                if (rows.length) {
                    var row0 = rows[0];
                    if (row0 && row0.Channel && !this.Channels.some(v => (v.Channel === row0.Channel))) {
                        this.Channels = this.Channels.concat(rows);
                    }
                }
                if (rows.length) {
                    state.loaded();
                }
                if (rows.length < this.limit) {
                    state.complete();
                }
            }).fail(() => {
                state.loaded();
                state.complete();
            })
        },
        refresh() {
            var size = this.Channels.length;
            if(!size || size > 200) return;
            $.ajax({
                method: "GET", // type: "GET", is also ok, method since jquery 1.9
                url: `/api/v1/getchannels`,
                global: false,
                data: {
                    q: this.query,
                    online: this.online,
                    start: 0,
                    limit: size,
                }
            }).then(data => {
                var rows = (data.LiveQing || data.NVR).Body.Channels || [];
                var chMap = this.Channels.reduce(function(pv, cv, idx, arr) {
                    var val = Object.assign({idx: idx}, cv);
                    pv[val.Channel] = val;
                    return pv;
                },{})
                for(var row of rows) {
                    var val = chMap[row.Channel];
                    if(val && val.idx < this.Channels.length) {
                        this.$set(this.Channels, val.idx, row);
                    }
                }
            }).fail(xhr => {
                xhr && console.log(`refresh channel error: ${xhr.status} ${xhr.responseText}`);
            })
        },
        formatStreamInfo(channelInfo) {
            var info = "";
            if(!channelInfo) return info;
            if(channelInfo.SourceVideoCodecName) {
                info = channelInfo.SourceVideoCodecName;
                if(info == "hevc") info = "h265";
                info += " ";
            }
            if(channelInfo.SourceVideoWidth && channelInfo.SourceVideoHeight) {
                info += `${channelInfo.SourceVideoWidth}x${channelInfo.SourceVideoHeight}`;
                info += " ";
            }
            info += `${channelInfo.InBitRate || 0}Kbps`;
            if(channelInfo.SourceVideoCodecName) {
                info += " ";
                info += `${channelInfo.SourceVideoFrameRate || 0}fps`;
            } else if(channelInfo.SourceAudioCodecName) {
                info += " ";
                info += `${channelInfo.SourceAudioCodecName}`;
            }
            return info;
        },
        showChannelLog(channelInfo) {
            this.$refs["channelLogDlg"].show(channelInfo);
        },
        keyDown(e) {
            if(e.keyCode == 17) {
                this.ctrl = true;
            }
        },
        keyUp(e) {
            if(e.keyCode == 17) {
                this.ctrl = false;
            }
        },
    }, //-- methods
    computed: {
        ...mapState(["userInfo", "serverInfo"]),
        onlineText() {
            var txt = "全部";
            switch(this.online) {
                case "yes":
                case "1":
                case "true":
                    txt = "在线";
                    break;
                case "no":
                case "0":
                case "false":
                    txt = "离线";
                    break;
            }
            return txt;
        }
    },
    beforeRouteEnter(to, from, next) {
        to.params.q = to.query.q;
        next(vm => {
            if(to.query.online) {
                vm.online = to.query.online;
                if(vm.online == "yes") {
                    vm.online = "1";
                }
            }
            if(to.query.online_dropdown) {
                vm.online_dropdown = to.query.online_dropdown == "yes";
            }
            vm.Channels = [];
            vm.ready();
            vm.timer = setInterval(() => {
                vm.refresh();
            }, 4000);
        });
    },
    beforeRouteUpdate(to, from, next) {
        if (to.params.mode != "icons") {
            return next({
                path: `/index/icons`,
                replace: true
            });
        }
        if(to.query.online) {
            this.online = to.query.online;
            if(this.online == "yes") {
                this.online = "1";
            }
        }
        if(to.query.online_dropdown) {
            this.online_dropdown = to.query.online_dropdown == "yes";
        }
        to.params.q = to.query.q;
        // this.$refs["search"].focus();
        this.Channels = [];
        if (this.timer) {
            clearInterval(this.timer);
            this.timer = 0;
        }
        next();
        this.$nextTick(() => {
            this.iconLoadMoreId = new Date().getTime();
            this.query = this.q;
            this.timer = setInterval(() => {
                this.refresh();
            }, 4000);
        });
    },
    beforeDestroy() {
        this.Channels = [];
        this.refreshChannels = [];
        if (this.timer) {
            clearInterval(this.timer);
            this.timer = 0;
        }
        $(document).off("keydown", this.keyDown).off("keyup", this.keyUp);
    },
    beforeRouteLeave(to, from, next) {
        this.Channels = [];
        if (this.timer) {
            clearInterval(this.timer);
            this.timer = 0;
        }
        next()
    }
};
</script>

<style lang="less" scoped>
@import url(~assets/styles/variables.less);

#input-online-dropdown {
    color: #444 !important;
    background-color: #f4f4f4 !important;
    border-color: #ddd !important;
}

#input-online-menu {
    min-width: unset;
}

.empty-channels {
    color: #ccc;
    font-weight: bold;
    font-size: 20px;
    text-align: center;
}

.view-icons {
    .error-offline {
        position: absolute;
        left: 30px;
        right: 30px;
        top: 10px;
        z-index: 999;
        color: orange;
        font-weight: bold;
    }

    .thumbnail {
        position: relative;
        overflow: hidden;

        .title {
            padding: 5px 5px 2px 5px;
        }

        .wrapper {
            padding-bottom: 55%;
            position: relative;
            height: auto;
        }

        .inner {
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;

            img {
                width: 100%;
                height: 100%;
                cursor: pointer;
            }
        }

        .record {
            position: absolute;
            top: 10px;
            right: 10px;
            color: white;
            font-size: 12px;
            background-color: fade(@base-active, 50%);
            padding: 2px 5px;
            cursor: pointer;
            border-radius: 10px;
            max-width: 120px;
            // overflow: hidden;
            // white-space: nowrap;
            // text-overflow: ellipsis;
        }

        .playback {
            position: absolute;
            top: 10px;
            right: 10px;
            color: white;
            font-size: 12px;
            background-color: fade(#666, 50%);
            padding: 2px 5px;
            cursor: pointer;
            border-radius: 10px;
            max-width: 120px;
            // overflow: hidden;
            // white-space: nowrap;
            // text-overflow: ellipsis;
        }

        .stream-info {
            position: absolute;
            bottom: 30px;
            color: white;
            font-size: 12px;
            background-color: fade(#666, 30%);
            padding: 2px 5px;
            border-radius: 10px;
            margin-right: 5px;
        }
    }

    .mask {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(236, 239, 246, 0.5);
    }
}
</style>
